import { fetcherResult } from 'amis-core/lib/types'
import axios, { AxiosRequestConfig, AxiosResponseHeaders, HttpStatusCode } from 'axios'
import { FetcherConfig } from 'amis-core/lib/factory'
import { Fetcher } from '@/components/amis/types/Fetcher'
import { AmisR, R } from '@/components/axios/interface'

class DefaultFetcher implements Fetcher {
	constructor() {}

	fetch = (fetcherConfig: FetcherConfig): Promise<fetcherResult> => {
		let {
			// eslint-disable-next-line prefer-const
			url, // 接口地址
			// eslint-disable-next-line prefer-const
			method, // 请求方法 get、post、put、delete
			data, // 请求数据
			// eslint-disable-next-line prefer-const
			responseType,
			// eslint-disable-next-line prefer-const
			configParam, // 其他配置
			// eslint-disable-next-line prefer-const
			headers, // 请求头
		} = fetcherConfig as any
		const config: AxiosRequestConfig = configParam || {}
		config.withCredentials = true
		responseType && (config.responseType = responseType)

		if (!config.transformResponse) {
			config.transformResponse = this.defaultTransformResponse
		}

		config.headers = headers || {}
		config
		if (method !== 'post' && method !== 'put' && method !== 'patch') {
			if (data) {
				config.params = data
			}
			return (axios as any)[method](url, config)
		} else if (data && data instanceof FormData) {
			config.headers = config.headers || {}
			config.headers['Content-Type'] = 'multipart/form-data'
		} else if (data && typeof data !== 'string' && !(data instanceof Blob) && !(data instanceof ArrayBuffer)) {
			data = JSON.stringify(data)
			config.headers = config.headers || {}
			config.headers['Content-Type'] = 'application/json'
		}
		return (axios as any)[method](url, data, config)
	}

	isCancel = (value: any) => {
		;(axios as any).isCancel(value)
	}

	private defaultTransformResponse = (data: any, headers: AxiosResponseHeaders, status?: number): AmisR<any> => {
		if (status != HttpStatusCode.Ok) {
			return data
		}
		const r: R = JSON.parse(data)
		if (this.isPageResponse(r)) {
			const pageR = {
				status: r.code,
				msg: r?.message,
				data: {
					items: r.data.content,
					total: r.data.totalElements,
				},
			}
			return pageR
		}
		return {
			status: r.code,
			msg: r?.message,
			data: r?.data,
		}
	}
	private isPageResponse = (r: R<any>): boolean => {
		return r.data && r.data.hasOwnProperty('content') && r.data.hasOwnProperty('totalElements')
	}
}

export default DefaultFetcher
